package br.com.foxinline.servico;

import br.com.foxinline.generico.ServicoGenerico;
import br.com.foxinline.modelo.Grupo;
import br.com.foxinline.modelo.Usuario;
import br.com.foxinline.util.GrupoUtilitario;
import br.com.foxinline.util.Msg;
import java.beans.Transient;
import java.security.Principal;
import java.util.List;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.ejb.Stateless;
import javax.faces.context.FacesContext;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Query;

/**
 *
 * @author ely
 */
@Stateless
@DeclareRoles(GrupoUtilitario.ADMINISTRADOR)
public class UsuarioServico extends ServicoGenerico<Usuario> {

    private Long quantidadeRegistrosResults;

    public UsuarioServico() {
        super(Usuario.class);
    }

    @Override
    @RolesAllowed(GrupoUtilitario.ADMINISTRADOR)
    public void delete(Usuario entity) {
        super.delete(entity);
    }

    @Override
    public void save(Usuario user) {
        user.setSenha(Usuario.encryptPassword(user.getSenha()));
        user.setId(null);
        super.save(user);
    }

    public void update(String confirm, String passwordOld, String passwordNew, Usuario user) {
        try {
            if (checkUserPassword(passwordOld, user)) {
                if (compareToPassword(confirm, passwordNew)) {
                    user.setSenha(Usuario.encryptPassword(passwordNew));
                    update(user);
                } else {
                    Msg.messagemError("Senhas não conferem");
                }
            } else {
                Msg.messagemError("Senha antiga não confere");
            }
        } catch (Exception e) {
            System.err.println(e);
        }

    }

    /**
     * Compara senha do usuário
     *
     * @param comparasenha
     * @param usuario
     * @return
     */
    public boolean compareToPassword(String confirm, Usuario user) {
        boolean b;
        if (user.getSenha().equals(confirm)) {
            b = true;
        } else {
            b = false;
        }
        return b;
    }

    public boolean compareToPassword(String confirm, String passwordNew) {
        boolean b;
        if (passwordNew.equals(confirm)) {
            b = true;
        } else {
            b = false;
        }
        return b;
    }

    /**
     * verifica se o campo name está vazio
     *
     * @param verificacampo
     * @return
     */
    public boolean checkUserName(Usuario user) {
        boolean b;
        if (!user.getNome().isEmpty()) {
            b = true;
        } else {
            b = false;
        }
        return b;
    }

    /**
     * Compara senha Cripitografada (Senha antiga)
     *
     * @param compara senha
     * @param cripitografia
     * @return
     */
    public boolean checkUserPassword(String senha, Usuario user) {
        boolean b;
        String s = Usuario.encryptPassword(senha);
        if (s.equals(user.getSenha())) {
            b = true;
        } else {
            b = false;
        }
        return b;
    }

    public Usuario existLogin(String login) {
        Usuario usuario;
        String sql = "Select u from Usuario u "
                + "where lower(u.login) like lower(:login)";
        Query query = getEntityManager().createQuery(sql);
        query.setParameter("login", login);
        List result = query.getResultList();
        try {
            if (result != null && !result.isEmpty()) {
                usuario = (Usuario) result.get(0);
            } else {
                usuario = null;
            }

        } catch (NoResultException e) {
            System.err.println(e);
            return null;
        } catch (NonUniqueResultException e) {
            System.err.println(e);
            return null;
        } catch (Exception e) {
            System.err.println(e);
            return null;
        }

        return usuario;
    }

    public Usuario verifySystemUserForLogin(String nome) {
        if (nome == null) {
            return null;
        }
        Usuario usr;
        try {
            final String sql = "select u from Usuario u where "
                    + "u.login like :nome";
            Query query = getEntityManager().createQuery(sql);
            query.setParameter("nome", nome);
            usr = (Usuario) query.getSingleResult();

        } catch (Exception e) {
            System.err.println(e);
            System.err.println("Nenhum usuário encontrado");
            return null;
        }
        return usr;
    }

    public Usuario getCurrentUser() {
        final Principal userPrincipal = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
        if (userPrincipal != null) {
            return verifySystemUserForLogin(userPrincipal.getName());
        }

        return null;
    }

    public String getNomeUsuario(String usuario) {
        String sql = "SELECT u.nome FROM Usuario u ";
        sql += " where ";

        if ((usuario != null) && !usuario.isEmpty()) {
            sql += " lower(u.login) like lower(:login) ";
        }
//        sql += " and u.ativo = TRUE";

        Query query = getEntityManager().createQuery(sql);

        if ((usuario != null) && !usuario.isEmpty()) {
            query.setParameter("login", usuario);
        }
        return (String) query.getSingleResult();
    }

    public boolean isAdmin() {

        Usuario usuario = getCurrentUser();

        return isAdminAuxiliar(usuario);
    }

    private boolean isAdminAuxiliar(Usuario usuario) {

        if (usuario != null) {

            for (Grupo grupo : usuario.getGrupos()) {
                if (grupo.getNome().toLowerCase().contains("administrador")) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Pesquisar Usuário
     *
     * @param pesquisarUsuario
     * @return
     */
    @Override
    public List<Usuario> find(Usuario entidade, Integer first, Integer pageSize) {

        String select = "select u ";
        String orderBy = "order by u.id asc";

        String sql = "from " + Usuario.class.getSimpleName() + " u ";

        if (entidade.getGrupos() != null && !entidade.getGrupos().isEmpty()) {
            String gruposId = "";
            for (int i = 0; i < entidade.getGrupos().size(); i++) {
                gruposId += entidade.getGrupos().get(i).getId();

                if (i < entidade.getGrupos().size() - 1) {
                    gruposId += ",";
                }
            }

            sql += "JOIN u.grupos g "
                    + "WHERE g.id in (" + gruposId + ") AND ";
        } else {
            sql += "WHERE ";
        }


        if (entidade.getNome() != null && !entidade.getNome().isEmpty()) {
            sql += "lower(u.nome) like lower(:nome) AND ";
        }

        if (entidade.getProfissao() != null && !entidade.getProfissao().isEmpty()) {
            sql += "lower(u.profissao) like lower(:profissao) AND ";
        }


        sql += "1=1";

        Query query = getEntityManager().createQuery(select.concat(sql).concat(orderBy));

        setQuantidadeRegistros(sql, query, entidade);

        setParameters(entidade, query);

        if (first != null && pageSize != null) {
            query.setFirstResult(first).setMaxResults(pageSize);
        }

        return query.getResultList();
    }

    @Transient
    private void setParameters(Usuario entidade, Query query) {

        if (entidade.getNome() != null && !entidade.getNome().isEmpty()) {
            query.setParameter("nome", "%" + entidade.getNome() + "%");
        }
        if (entidade.getProfissao() != null && !entidade.getProfissao().isEmpty()) {
            query.setParameter("profissao", "%" + entidade.getProfissao() + "%");
        }
    }

    private void setQuantidadeRegistros(String sql, Query query, Usuario entidade) {

        String select = "SELECT count(u) ";

        query = getEntityManager().createQuery(select + sql);

        setParameters(entidade, query);

        quantidadeRegistrosResults = (Long) query.getSingleResult();
    }

    @Override
    public Long quantidadeRegistros() {
        return quantidadeRegistrosResults;
    }

    public boolean isAcessoTelasUsuario() {

        for (Grupo grupo : getCurrentUser().getGrupos()) {
            if (grupo.getNome().toLowerCase().contains("administrador")
                    || grupo.getNome().toLowerCase().contains("gerente")
                    || grupo.getNome().toLowerCase().contains("secretario")) {
                return true;
            }
        }

        return false;
    }

    /**
     * autocomplete Usuário
     *
     * @param pesquisarUsuario
     * @return
     */
    public List<Usuario> autocomplete(String nome) {

        String sql = "select u from " + Usuario.class.getSimpleName() + " u  ";

        if (nome != null) {
            sql += "WHERE lower(u.nome) like lower(:nome)";
        }

        sql += " order by u.nome asc";

        Query query = getEntityManager().createQuery(sql);

        if (nome != null) {
            query.setParameter("nome", "%" + nome + "%");
        }

        return query.getResultList();
    }
}
